package team.zero.lemon.pattern;/**
 * Created by bolin on 2016/12/6.
 */

import javafx.application.Application;
import javafx.stage.Stage;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class App extends Application {

    public static void main(String[] args) {
        App pc = new App();

        SyncStack s = pc.new SyncStack();

        ExecutorService service = Executors.newCachedThreadPool();
        Producer p = pc.new Producer("张三", s);
        Producer p2 = pc.new Producer("李四", s);
        Consumer c = pc.new Consumer("王五", s);
        Consumer c2 = pc.new Consumer("老刘", s);
        Consumer c3 = pc.new Consumer("老林", s);
        service.submit(p);
        service.submit(c);
        service.submit(c2);
        service.submit(c3);


    }

    @Override
    public void start(Stage primaryStage) {

    }


    class Producer implements Runnable {
        private String name;
        private SyncStack s = null;

        public Producer(String name, SyncStack s) {
            this.name = name;
            this.s = s;
        }

        @Override
        public void run() {
            try {
//                while (true) {
//                    Product product = new Product((int) (Math.random() * 10000)); // 产生0~9999随机整数
//                    System.out.println(name + "准备生产(" + product.toString() + ").");
//                    s.push(product);
//                    System.out.println(name + "已生产(" + product.toString() + ").");
//                    System.out.println("===============");
//                    Thread.sleep(500);
//                }
                // 开始生产馒头
                for (int i = 0; i < 60; i++) {
                    SteamBread stb = new SteamBread(i);
                    s.push(stb);
                    System.out.println(name+"生产了" + stb);
                    try {
                        Thread.sleep(10);//每生产一个馒头，睡觉10毫秒
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class Consumer implements Runnable {
        private String name;
        private SyncStack s = null;

        public Consumer(String name, SyncStack s) {
            this.name = name;
            this.s = s;
        }

        @Override
        public void run() {
            try {
//                while (true) {
//                    System.out.println(name + "准备消费产品.");
//                    Product product = s.pop();
//                    System.out.println(name + "已消费(" + product.toString() + ").");
//                    System.out.println("===============");
//                    Thread.sleep(500);
//                }
                for (int i = 0; i < 20; i++) {//开始消费馒头
                    SteamBread stb = s.pop();
                    System.out.println(name+"消费了" + stb);
                    try {
                        Thread.sleep(1000);//每消费一个馒头，睡觉100毫秒。即生产多个，消费一个
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class SteamBread {
        int id;//馒头编号

        SteamBread(int id) {
            this.id = id;
        }

        public String toString() {
            return "steamBread:" + id;
        }
    }

    class SyncStack {
        int index = 0;
        SteamBread[] stb = new SteamBread[6];//构造馒头数组，相当于馒头筐，容量是6

        //放入框中，相当于入栈
        public synchronized void push(SteamBread sb) {
            while (index == stb.length) {//筐满了，即栈满，
                try {
                    System.out.println("筐满了,让当前线程等待");
                    this.wait();//让当前线程等待
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            this.notify();//唤醒在此对象监视器上等待的单个线程，即消费者线程
            stb[index] = sb;
            this.index++;
        }

        //从框中拿出，相当于出栈
        public synchronized SteamBread pop() {
            while (index == 0) {//筐空了，即栈空
                try {
                    System.out.println("筐空了,让消费线程等待");
                    this.wait();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            this.notify();
            this.index--;//push第n个之后，this.index++，使栈顶为n+1，故return之前要减一
            return stb[index];
        }
    }

    class Storage {
        BlockingQueue<Product> queues = new LinkedBlockingQueue<Product>(10);

        public void push(Product p) throws InterruptedException {
            queues.put(p);
        }

        public Product pop() throws InterruptedException {
            return queues.take();
        }

    }

    class Product {
        private int id;

        public Product(int id) {
            this.id = id;
        }

        public String toString() {// 重写toString方法
            return "产品：" + this.id;
        }

    }
}